package nz.ac.massey.doi_information_extractor.parser;

import java.io.BufferedInputStream;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.commons.lang3.StringEscapeUtils;

import nz.ac.massey.doi_information_extractor.data.Author;
import nz.ac.massey.doi_information_extractor.data.AuthorList;
import nz.ac.massey.doi_information_extractor.data.Publication;

public class SpringerPlugin implements PluginInterface {

	private String doi;
	public Publication result = new Publication();

	public SpringerPlugin(String inputdoi) {
		this.doi = inputdoi;
	}

	@Override
	public void getInformationFromDOI(String doi) throws PublicationNotFoundException,
			IOException {

		// Get the page with search results for the DOI.
		URL resolvedPage;
		try {
			if (doi.contains("dx.doi.org")) {
				resolvedPage = new URL(doi);
			}
			else {
				resolvedPage = new URL("http://dx.doi.org/" + doi);
			}
		} catch (MalformedURLException e) {
			throw new PublicationNotFoundException(e.getMessage());
		}

		URLConnection doiConnection = resolvedPage.openConnection();
		doiConnection.setRequestProperty("User-Agent", "Mozilla 5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.0.11) ");
		
		BufferedInputStream buffer = new BufferedInputStream(doiConnection.getInputStream());

		StringBuilder builder = new StringBuilder();
		int byteRead;
		while ((byteRead = buffer.read()) != -1){
			builder.append((char) byteRead);
		}
		buffer.close();

		// Put the source together.
		String source = builder.toString();
		source = StringEscapeUtils.unescapeHtml4(source);
		
		result.setAuthors(getAuthors(source));
		
		result.setArticleTitle(getArticleTitle(source));
		
		result.setPublicationTitle(getPublicationTitle(source));
		
		result.setPageNumbers(getPageNumbers(source));
		
		result.setVolumeNumber(getVolumeNumber(source));
		
		result.setEdition(getIssueNumber(source));
		
		// This means that there won't be random URL's floating around. However, it does mean that if the article title isn't found, the URl will never be filled. 
		if (result.getArticleTitle() != "") {
		result.setUrl(getURL(doiConnection));
		}
	}
	
	private String getIssueNumber(String source) {
		String issue = "";
		Pattern issuePatt = Pattern.compile(
				"title=\"Link to the Issue of this Article\">.*</a>, <span class=\"pagination\">", Pattern.UNIX_LINES);
		Matcher issueMat = issuePatt.matcher(source);
		if (issueMat.find() == true) {
			issue = source.substring(issueMat.start() + 42, issueMat.end() - 31);
			issue = issue.split(" ")[3];
		}
		return issue;
	}

	private String getURL(URLConnection source){
		String url = "http://www.springerlink.com/content/" + source.getURL().getPath().split("/")[2] + "/fulltext.pdf";
		return url;
	}
	
	private String getVolumeNumber(String source) {
		String volume = "";
		Pattern volumePatt = Pattern.compile(
				"title=\"Link to the Issue of this Article\">.*</a>, <span class=\"pagination\">", Pattern.UNIX_LINES);
		Matcher volumeMat = volumePatt.matcher(source);
		if (volumeMat.find() == true) {
			volume = source.substring(volumeMat.start() + 42, volumeMat.end() - 33);
			volume = volume.split(" ")[1];
			volume = volume.substring(0, volume.length() - 1);
		}
		return volume;
	}

	private String getPublicationTitle(String source) {
		String title = "";
		Pattern titlePatt = Pattern.compile(
				"title=\"Link to the Journal of this Article\">.*</a>", Pattern.UNIX_LINES);
		Matcher titleMat = titlePatt.matcher(source);
		if (titleMat.find() == true) {
			title = source.substring(titleMat.start() + 44, titleMat.end() - 4);
		}
		return title;
	}
	
	
	private String getPageNumbers(String source) {
		String pages = "";
		Pattern pagesPatt = Pattern.compile(
				"<span class=\"pagination\">.*</span><span class=\"doi\">", Pattern.UNIX_LINES);
		Matcher pagesMat = pagesPatt.matcher(source);
		if (pagesMat.find() == true) {
			pages = source.substring(pagesMat.start() + 25, pagesMat.end() - 25);
		}
		return pages;
	}

	private String getArticleTitle(String source) {
		String articleTitle = "";
		Pattern titlePatt = Pattern.compile(
				"<h1 lang=\"en\" class=\"title\">.*</h1><p class=\"authors\">", Pattern.DOTALL);
		Matcher titleMat = titlePatt.matcher(source);
		if (titleMat.find() == true) {
			articleTitle = source.substring(titleMat.start(), titleMat.end());
		}
		if (articleTitle != "") {
			articleTitle = articleTitle
					.substring(33, articleTitle.length() - 28);
		}

		return articleTitle;
	}

	private AuthorList getAuthors(String source) {
			AuthorList authorsList = new AuthorList();
			String authorsString = "";
			Pattern authorsPatt = Pattern.compile("<p class=\"authors\">.*</p>",
					Pattern.UNIX_LINES);
			Matcher authorsMat = authorsPatt.matcher(source);
			if (authorsMat.find()) {
				authorsString = source.substring(authorsMat.start(),
						authorsMat.end());
			}
			if (authorsString != "") {
				authorsString = authorsString.substring(19,
						authorsString.length() - 4);

				while (authorsString.contains("<a")) {
					String authorsStringRemoveAs = authorsString.substring(authorsString.indexOf("<a"),authorsString.indexOf("\">") + 2);
					authorsString = authorsString.replace(authorsStringRemoveAs, "");
					try {
					authorsStringRemoveAs = authorsString.substring(authorsString.indexOf("</a>"), authorsString.indexOf("</a>") + 4);
					authorsString = authorsString.replace(authorsStringRemoveAs, "");
					}
					catch (StringIndexOutOfBoundsException e) {
						continue;
					}
				}
				

				String[] authorsFurtherString = authorsString.split(" ");
				
				// This is a little more tricky than the other methods, as it has to
				// fill the AuthorList with Author objects. It will make mistakes if
				// someone is called 'and'.
				Author tempAuthor = new Author();
				for (int i = 0; i < authorsFurtherString.length; i++) {

					if (authorsFurtherString[i].equals("and")) {
						continue;
					}

					if (tempAuthor.getAuthorFirstName() == "") {
						tempAuthor.setAuthorFirstName(authorsFurtherString[i]);
					} else {
						tempAuthor.setAuthorLastName(authorsFurtherString[i]);
						authorsList.add(tempAuthor);
						tempAuthor = new Author();
					}
				}
			}
			return authorsList;
		}
	
	
	
	@Override
	public Publication call() throws Exception {
		getInformationFromDOI(doi);
		return result;
	}
}
